﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using Umi.Web.Filters;
using Umi.Web.Metadatas.Configurations;

namespace Umi.Web
{
    public class Startup
    {

        private readonly IConfiguration configuration;

        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
            Regex.CacheSize = 10;
        }

        //依赖注入配置,替换默认服务容器
        public void ConfigureServices(IServiceCollection services)
        {
            //注册Session支持
            //Session 存储方式可以使用如下方式
            //非分布式的
            services.AddMemoryCache();

            if (configuration.GetValue<bool>("UseRedis"))
            {
                //存储到Redis服务器上
                string redis = configuration.GetConnectionString("Redis");
                services.AddDistributedRedisCache(ss => ss.Configuration = redis);
            }
            else
            {
                //使用分布式的内存缓存
                services.AddDistributedMemoryCache();
            }
            //存储到SqlServer服务器上，参数为SqlServer中的表，字段，连接等配置
            //services.AddDistributedSqlServerCache(ss => ss.ConnectionString = conStr);
            // services.AddMysqlCache(ss => ss.ConnectionString = Configuration.GetConnectionString("Mysql"));
            //添加Session支持
            services.AddSession(p =>
            {
                p.Cookie = new CookieBuilder()
                {
                    HttpOnly = true,
                    IsEssential = true,
                    Name = ".Umi.Session",
                    SameSite = SameSiteMode.None
                };
                p.IdleTimeout = TimeSpan.FromMinutes(40);
            });

            CorsConfiguration corsConfig = new CorsConfiguration();
            configuration.Bind("CorsConfiguration", corsConfig);

            //注册跨域资源共享
            //解释：https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
            //参考：http://www.ruanyifeng.com/blog/2016/04/cors.html
            services.AddCors(p =>
            {
                p.AddDefaultPolicy(cpb =>
                {
                    cpb.AllowCredentials();
                    cpb.WithExposedHeaders(corsConfig.ExposedHeaders ?? new string[0]);
                    cpb.WithHeaders(corsConfig.Headers ?? new string[0]);
                    cpb.WithMethods(corsConfig.Methods ?? new string[0]);
                    cpb.WithOrigins(corsConfig.Origins ?? new string[0]);
                });
            });

            //GDPR
            //参考：https://www.gdpr.net/
            //注解：https://docs.microsoft.com/zh-cn/aspnet/core/security/gdpr?view=aspnetcore-2.1
            //说明：http://www.cnblogs.com/GuZhenYin/p/9154447.html
            services.Configure<CookiePolicyOptions>(p =>
            {
                p.CheckConsentNeeded = ctx => false;
                p.MinimumSameSitePolicy = SameSiteMode.None;
                p.Secure = CookieSecurePolicy.None;
            });
            //将配置文件节注册到实体中
            //services.Configure<Entity>(Configuration.GetSection("sss"));

            //注册EF Core
            //string conStr = Configuration.GetConnectionString("Mysql");


            //如果使用SqlServer，则替换上两句为下面两句
            //services.AddEntityFrameworkSqlServer();
            //services.AddDbContext<EntityFrameworkDbContext>(ss => ss.UseSqlServer(conStr));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseStaticFiles();
            app.UseSession();

            IServiceProvider provider = app.ApplicationServices;
            foreach (var item in Program.InitedStartup)
            {
                Type type = item.GetType();
                var method = type.GetMethod("Configure");
                if (method == null)
                    continue;
                var param = method.GetParameters();
                var ins = Program.GetParametersObj(param, provider);
                for (int i = 0; i < param.Length; i++)
                {
                    if (param[i].ParameterType == typeof(IApplicationBuilder))
                        ins[i] = app;
                }
                method.Invoke(item, ins);
            }


            app.UseRouting();
            app.UseEndpoints(cfg => cfg.MapDefaultControllerRoute());



            foreach (var item in Program.InitedStartup)
            {
                Type type = item.GetType();
                var method = type.GetMethod("ConfigureAfterMvc");
                if (method == null)
                    continue;
                var param = method.GetParameters();
                var ins = Program.GetParametersObj(param, provider);
                for (int i = 0; i < param.Length; i++)
                {
                    if (param[i].ParameterType == typeof(IApplicationBuilder))
                        ins[i] = app;
                }
                method.Invoke(item, ins);
            }

        }

    }
}
